package com.xbongbong.paas.help;

import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.pojo.vo.ProcessOperateVo;
import com.xbongbong.paas.pojo.vo.ProcessTemplateNodeVO;
import com.xbongbong.paas.pojo.workflow.task.dto.WorkflowNodeTaskGetDTO;
import com.xbongbong.paas.pojo.workflow.task.vo.WorkflowNodeTaskGetVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.model.impl.FormLabelModelImpl;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.domain.entity.ext.WorkflowTaskNodeEntityExt;
import com.xbongbong.workflow.model.WorkflowTaskNodeModel;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.nodes.ApprovalNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 吴峰
 * @date 2023/01/06 9:59
 */
@Component
@Slf4j
public class WorkflowOperateHelp {

    @Resource
    private UserInfoHelp userInfoHelp;
    @Resource
    private WorkflowTaskNodeModel workflowTaskNodeModel;


    public void dealDingtalkParameter(WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO) {
        String userId = workflowNodeTaskGetDTO.getUserId();
        String corpid = workflowNodeTaskGetDTO.getCorpid();
        Long taskId = workflowNodeTaskGetDTO.getProcessTaskId();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("userId", userId);
        params.put("corpid", corpid);
        params.put("del", 0);
        params.put("taskId", taskId);
        params.put("orderByStr", " add_time DESC, id DESC ");
        List<WorkflowTaskNodeEntityExt> extEntities = workflowTaskNodeModel.findExtEntities(params);
        if (CollectionUtils.isNotEmpty(extEntities)) {
            WorkflowTaskNodeEntityExt workflowTaskNodeEntityExt = extEntities.get(0);
            workflowNodeTaskGetDTO.setProcessType(ProcessTypeEnum.TODO.getValue());
            workflowNodeTaskGetDTO.setProcessNodeTaskId(workflowTaskNodeEntityExt.getId());
            if(extEntities.size() > 1){
                //获取当前节点的所有tasknode，可能有抄送、审批。（回退的可以不用考虑，这里只需要确定当前节点是否有审批节点即可）
                List<WorkflowTaskNodeEntityExt> currentTaskNodeList = extEntities.stream().filter(v -> Objects.equals(v.getWorkflowNodeId(), workflowTaskNodeEntityExt.getWorkflowNodeId())).sorted(Comparator.comparing(WorkflowTaskNodeEntityExt::getAddTime).reversed()).collect(Collectors.toList());
                for (WorkflowTaskNodeEntityExt taskNodeEntityExt : currentTaskNodeList) {
                    //若存在审批节点且未审批，则取此节点为当前节点
                    if(Objects.equals(taskNodeEntityExt.getNodeType(), NodeTypeEnum.PROCESS_NODE.getNodeType()) && Objects.equals(taskNodeEntityExt.getTaskType(), TaskTypeEnum.UNTREATED.getType())){
                        workflowNodeTaskGetDTO.setProcessNodeTaskId(taskNodeEntityExt.getId());
                        break;
                    }
                }
            }
        }
    }
    /**
     * 获取流程操作
     *
     */
    public void getProcessOperator(WorkflowNodeEntityExt workflowNodeEntity, WorkflowNodeTaskGetDTO workflowNodeTaskGetDTO, WorkflowNodeTaskGetVO workflowNodeTaskGetVO,
                                    WorkflowEntity workflowEntity, WorkflowTaskNodeEntity workflowTaskNodeEntity, Map<String, UserEntity> userMap, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {

        List<ProcessOperateVo> resultList = new ArrayList<>();
        ProcessTemplateNodeVO processOperatePermission = new ProcessTemplateNodeVO();
        try {

            // 允许提交且不是撤回的流程
            ApprovalNode approvalNode = JsonHelperUtil.parseObject(workflowNodeEntity.getConfigData(), ApprovalNode.class);

            if (Objects.equals(workflowTaskNodeEntity.getUserId(), workflowNodeTaskGetDTO.getLoginUser().getUserId()) && (Objects.equals(workflowTaskNodeEntity.getTaskType(), TaskTypeEnum.UNTREATED.getType()) || Objects.equals(workflowTaskNodeEntity.getNodeType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType()))) {

                boolean unRevokeFlag = !Objects.equals(workflowNodeEntity.getType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType())
                        && Objects.equals(workflowNodeTaskGetDTO.getProcessType(), ProcessTypeEnum.TODO.getValue());
                boolean commitFlag = unRevokeFlag && Objects.equals(approvalNode.getCommitFlag(), 1);

                if (commitFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(approvalNode.getCommitText());
                    operatePoJo.setFlag(approvalNode.getCommitFlag());
                    operatePoJo.setType(TaskTypeEnum.COMMIT.getType());
                    resultList.add(operatePoJo);
                }
                // 允许结束且不是撤回的流程
                boolean endFlag = unRevokeFlag && Objects.equals(approvalNode.getEndFlag(), 1);
                if (endFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(approvalNode.getEndText());
                    operatePoJo.setFlag(approvalNode.getEndFlag());
                    operatePoJo.setType(TaskTypeEnum.END.getType());
                    resultList.add(operatePoJo);
                }
                // 允许暂存且不是撤回的流程
                boolean storageFlag = unRevokeFlag && Objects.equals(approvalNode.getStorageFlag(), 1);
                if (storageFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(approvalNode.getStorageText());
                    operatePoJo.setFlag(approvalNode.getStorageFlag());
                    operatePoJo.setType(TaskTypeEnum.STORAGE.getType());
                    resultList.add(operatePoJo);
                }
                // 允许回退且不是撤回的流程
                boolean backFlag = unRevokeFlag && Objects.equals(approvalNode.getBackFlag(), 1);
                if (backFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(approvalNode.getBackText());
                    operatePoJo.setFlag(approvalNode.getBackFlag());
                    operatePoJo.setType(TaskTypeEnum.BACK.getType());
                    resultList.add(operatePoJo);
                }
                // 允许转交且不是撤回的流程
                boolean transferFlag = unRevokeFlag && Objects.equals(approvalNode.getTransferFlag(), 1);
                if (transferFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(approvalNode.getTransferText());
                    operatePoJo.setFlag(approvalNode.getTransferFlag());
                    operatePoJo.setType(TaskTypeEnum.TRANSFER.getType());
                    resultList.add(operatePoJo);
                    if (CollectionUtils.isNotEmpty(approvalNode.getTransferUserList())) {
                        List<UserVO> transferUserList = userInfoHelp.getUserList(workflowNodeEntity.getTransferUserList(), workflowNodeTaskGetDTO.getCorpid());
                        for (UserVO user : transferUserList) {
                            if (Objects.equals(user.getDel(), DelEnum.DELETE.getDel())) {
                                String name = user.getName();
                                user.setName(name + "(" + I18nMessageUtil.getMessage(CommonConstant.LEAVE) + ")");
                            }
                        }
                        processOperatePermission.setTransferUserList(transferUserList);
                    }
                }
                // 允许撤回，流程状态为待审批，当前用户为创建人，当前列表是我提交的 显示撤回按钮
                boolean revokeFlag = Objects.equals(workflowEntity.getAllowWithdraw(), 1)
                        && Objects.equals(workflowNodeTaskGetVO.getFlowStatus(), FlowStatusEnum.APPROVAL_PENDING.getType())
                        && workflowNodeTaskGetVO.getCommitUser().getUserId().equals(workflowNodeTaskGetDTO.getUserId())
                        && Objects.equals(workflowNodeTaskGetDTO.getProcessType(), ProcessTypeEnum.CREATE.getValue());
                if (revokeFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(TaskTypeEnum.REVOKE.getMemo());
                    operatePoJo.setFlag(1);
                    operatePoJo.setType(TaskTypeEnum.REVOKE.getType());
                    resultList.add(operatePoJo);
                }

                // 允许加签流程
                boolean addSignatureFlag = unRevokeFlag && Objects.equals(approvalNode.getAddSignatureFlag(), BasicConstant.ONE);
                if (addSignatureFlag && !Objects.equals(workflowTaskNodeEntity.getAddSignature(), BasicConstant.ONE)) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(approvalNode.getAddSignatureText());
                    operatePoJo.setFlag(approvalNode.getAddSignatureFlag());
                    operatePoJo.setType(TaskTypeEnum.ADD_SIGNATURE.getType());
                    resultList.add(operatePoJo);
                }

                // 流程被拒绝 || 被撤回的流程 当前用户为创建人 显示重新提交
                boolean againFlag = false;
                if (Objects.equals(WorkflowOperateEnum.ADD.getType(), workflowTransferPOJO.getOperate())) {
                    // 新建时，存在结束任务和撤回任务则表示可以重新提交
                    String corpid = workflowNodeTaskGetDTO.getCorpid();
                    Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put(StringConstant.CORPID, corpid);
                    param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                    param.put("taskTypeIn", Arrays.asList( TaskTypeEnum.END.getType(), TaskTypeEnum.REVOKE.getType()));
                    param.put("taskId", workflowTaskNodeEntity.getTaskId());
                    param.put("formId", workflowEntity.getFormId());
                    Integer count = workflowTaskNodeModel.getEntityCount(param);
                    if (!Objects.equals(count, BasicConstant.ZERO)) {
                        againFlag = true;
                    }
                    if (Objects.equals(workflowTaskNodeEntity.getTaskType(), TaskTypeEnum.AGAIN_COMMIT.getType())) {
                        againFlag = false;
                    }
                }
                if (againFlag) {
                    ProcessOperateVo operatePoJo = new ProcessOperateVo();
                    operatePoJo.setText(TaskTypeEnum.AGAIN_COMMIT.getMemo());
                    operatePoJo.setFlag(1);
                    operatePoJo.setType(TaskTypeEnum.AGAIN_COMMIT.getType());
                    resultList.add(operatePoJo);
                }

            }

            //　系统提交
            boolean systemCommit = Objects.equals(workflowNodeTaskGetDTO.getProcessType(), ProcessTypeEnum.ALL.getValue())
                    && Objects.equals(workflowTaskNodeEntity.getUserId(), PaasConstant.SYS_USER_ID)
                    && !Objects.equals(workflowNodeEntity.getType(), NodeTypeEnum.START_PROCESS_NODE.getNodeType());
            // 离职人员需要转交按钮
            boolean isDismiss = Objects.equals(workflowNodeTaskGetDTO.getProcessType(), ProcessTypeEnum.ALL.getValue())
                    && (!userMap.containsKey(workflowTaskNodeEntity.getUserId())
                    || Objects.equals(userMap.get(workflowTaskNodeEntity.getUserId()).getDel(), 1));
            if(systemCommit || isDismiss) {
                ProcessOperateVo operatePoJo = new ProcessOperateVo();
                operatePoJo.setText(TaskTypeEnum.SYSTEM_COMMIT.getMemo());
                operatePoJo.setFlag(1);
                operatePoJo.setType(TaskTypeEnum.SYSTEM_COMMIT.getType());
                resultList.add(operatePoJo);
            }else{
                //先补丁一下，现在前端是传最后一个taskNodeId来请求的，所以如果是多人节点，前面的taskNode上面是离职，就会丢失系统转交按钮
                //后续“超管可以处理审批中流程”的需求上线后能兼容这种情况，就不需要这个补丁了 --2022.12.16
                if(Objects.equals(workflowNodeTaskGetDTO.getProcessType(), ProcessTypeEnum.ALL.getValue())
                        && workflowNodeTaskGetDTO.getLoginUser().isAdminOrBoss()){
                    //如果当前节点，待处理人员全是离职人员，则需要系统转交按钮
                    Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    params.put("corpid", workflowNodeEntity.getCorpid());
                    params.put("taskId", workflowTaskNodeEntity.getTaskId());
                    params.put("taskType", TaskTypeEnum.UNTREATED.getType());
                    params.put("del", 0);
                    List<WorkflowTaskNodeEntityExt> extEntities = workflowTaskNodeModel.findExtEntities(params);
                    if(CollectionsUtil.isNotEmpty(extEntities)){
                        List<String> userIds = extEntities.stream().map(WorkflowTaskNodeEntity::getUserId).collect(Collectors.toList());
                        boolean allLeaveFlag = true;
                        for (String userId : userIds) {
                            UserEntity userEntity = userMap.get(userId);
                            if(Objects.nonNull(userEntity) && Objects.equals(userEntity.getDel(), DelEnum.NORMAL.getDel())){
                                allLeaveFlag = false;
                                break;
                            }
                        }
                        if(allLeaveFlag){
                            ProcessOperateVo operatePoJo = new ProcessOperateVo();
                            operatePoJo.setText(TaskTypeEnum.SYSTEM_COMMIT.getMemo());
                            operatePoJo.setFlag(1);
                            operatePoJo.setType(TaskTypeEnum.SYSTEM_COMMIT.getType());
                            resultList.add(operatePoJo);
                        }
                    }
                }
            }


            processOperatePermission.setOpinionFlag(approvalNode.getOpinionFlag());
            processOperatePermission.setBackType(approvalNode.getBackType());
            processOperatePermission.setProcessOperate(resultList);
            workflowNodeTaskGetVO.setProcessOperatePermission(processOperatePermission);
        } catch (Exception e) {
            log.error("工作流获取流程操作权限出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }
}
